/**
 * @(#)Board2.java
 *
 *
 * @author 
 * @version 1.00 2008/4/28
 */
package Checkers;

import java.util.Arrays;

public class Board implements Cloneable {
    private byte board[];
    private byte player;
    private int value;
    
    /**
     * CONSTRUCTORS
     */
    public Board() {
        value=0;
        board = new byte[37];
        for (int i=1; i<36; i++) {
            if (i==9||i==18||i==27) { board[i] = -1; i++; }
            if (i < 14)
                board[i] = 2;
            else if (i < 23)
                board[i] = 0;
            else
                board[i] = 1;
        }
        board[0] = board[36] = -1;
        this.player = 1;    // red = 1, black = 2
    }
    
    public Board(byte[] board, byte player) {
        value=0;
        this.board = new byte[37];
        for (int i=1; i<36; i++) {
            this.board[i] = board[i];
        }
        this.board[0] = this.board[36] = -1;
        this.player = player;   // red = 1, black = 2
    }
    
    /**
     * PLAYER functions
     */
    public byte getPlayer() { return player; }
    public void nextPlayer() { player = (byte)((player > 1) ? 1 : 2); }
    
    /**
     * getBoard
     * returns the board in matrix format
     */
    public byte[][] getBoard() { 
        byte[][] matrix = new byte[8][8];
        int x = 0, i = 35;
        for (int y = 0; y < 8; y++) {
            if (y%2 == 0)   x = 1;
            else            x = 0;
            for (; x < 8; x+=2) {
                matrix[y][x] = board[i];
                i--;
                if (i==9||i==18||i==27)
                    i--;
            }
        }
        return matrix;
    }
    
    public byte[] getByteBoard() { return board; }
    
    //X is vertical, Y is horizontal
    /**
     * getPieceAt
     * returns the piece at board[y][x], duh
     * Ay + Bx + C = i, where A = -.5, B = -4.5, C = 35.5
     */
    public byte getPieceAt(int x, int y) { 
         if (x < 0 || x >= 8 || y < 0 || y >= 8)
             return -1;
        return board[(byte)(y * -.5 + x * -4.5 + 35.5)]; 
    }
    public byte getPieceAt(Coord c) { 
        if (c.x < 0 || c.x >= 8 || c.y < 0 || c.y >= 8)
            return -1;
        return board[(byte)(c.y * -.5 + c.x * -4.5 + 35.5)]; 
    }
    
    /**
     * getKingAt
     * returns the king at board[y][x]
     * legacy function; totally useless
     */
    public byte getKingAt(Coord c) {
        byte piece = getPieceAt(c);
        return piece < 4 ? 0 : piece;
    }
     
    
    /**
     * makeMove
     * performs necessarily valid set of moves on board
     */
    public byte makeMove(Move m) {
        Coord move = m.start(), nextMove;
        byte numJumped = 0;
        int moveIndex, nextMoveIndex;
        moveIndex = (byte)(move.y * -.5 + move.x * -4.5 + 35.5);
        do {
            nextMove = m.next();
            nextMoveIndex = (byte)(nextMove.y * -.5 + nextMove.x * -4.5 + 35.5);
            // generally speaking, this should be valid
            if (board[moveIndex] != 0 && board[nextMoveIndex] == 0) {
                // remove jumped piece
                if (moveIndex > nextMoveIndex) {
                    if (moveIndex - nextMoveIndex == 10) {              // backward left jump
                        board[moveIndex-5] = 0;
                        numJumped++;
                    } else if (moveIndex - nextMoveIndex == 8) {        // backward right jump
                        board[moveIndex-4] = 0;
                        numJumped++;
                    }
                } else if (moveIndex < nextMoveIndex) {
                    if (nextMoveIndex - moveIndex == 10) {              // forward right jump
                        board[moveIndex+5] = 0;
                        numJumped++;
                    } else if (nextMoveIndex - moveIndex == 8) {        // forward left jump
                        board[moveIndex+4] = 0;
                        numJumped++;
                    }
                }
                // move to new position
                if (nextMoveIndex > 31 || nextMoveIndex < 5)            // if the move ends in the last row
                    board[nextMoveIndex] = (byte)(player + 3);          // make king
                else
                    board[nextMoveIndex] = board[moveIndex];            // otherwise, whatever it was before                        
                // clear the old spot
                board[moveIndex] = 0;
                
                moveIndex=nextMoveIndex;
            } 
            // wtf, get out of here
            else
            {
                return -1;
            }
            
            move = nextMove;
            
        } while (!m.isEmpty());
        
        nextPlayer();
        return numJumped;
    }
    
    /**
     * getAdjacentTo
     * returns coordinates of squares directly adjacent to given coordinate
     */
    public Coord[] getAdjacentTo(int x, int y) {
        int index = (byte)(y * -.5 + x * -4.5 + 35.5);
//      System.out.println("("+x+":"+y+") "+index);
        Coord neighbors[] = new Coord[4];
        int num = 0;
        if (index > 4) {
            if (board[index-5] != -1)   { neighbors[num] = new Coord(x+1, y+1); num++; }
            if (board[index-4] != -1)   { neighbors[num] = new Coord(x+1, y-1); num++; }
        }
        if (index < 32) {
            if (board[index+5] != -1)   { neighbors[num] = new Coord(x-1, y-1); num++; }
            if (board[index+4] != -1)   { neighbors[num] = new Coord(x-1, y+1); num++; }
        }
  
        //floods the console
//        for (int i=0; i<neighbors.length; i++)
//          System.out.print(neighbors[i]);
//        System.out.println();
        
        if (num == 4)
            return neighbors;
        if (num == 0)
            return null;
        
        Coord adjStates[] = Arrays.copyOf(neighbors, num); // truncate the array
        return adjStates;
    }
        
    /**
     * printBoard
     */
    public void printBoard() {
        byte b[][] = getBoard();
        for (int i =0; i<8; i++) {
            for (int j =0; j<8; j++)
                System.out.print(b[i][j]);
            System.out.println();
        }
    }
    
    public Board clone() {
        return new Board(board, player);
    }    
    
    
    public int getValue()
    {
        return value;
    }
    
    public void setValue(int v)
    {
        value=v;
    }
}